/**
 *                     Remixvym (version 0.8.3)
 *             Copyright (c) 2010 by RemixLab, DISI-UNAL
 *            http://www.disi.unal.edu.co/grupos/remixlab/
 *
 * This Java package provides classes to visualize Mind Maps created in VYM
 * (View Your Mind) in a Processing Sketch
 *
 * @author Alvaro Lopez, Juan Baquero
 *
 * This source file is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 3 of the License, or (at your option)
 * any later version.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * A copy of the GNU General Public License is available on the World Wide Web
 * at <http://www.gnu.org/copyleft/gpl.html>. You can also obtain it by
 * writing to the Free Software Foundation, 51 Franklin Street, Fifth Floor
 * Boston, MA 02110, USA
 */
package remixlab.remixvym.core.graphics;

import java.util.ArrayList;

import processing.core.PApplet;
import processing.core.PFont;
import processing.xml.XMLElement;
import remixlab.remixvym.core.graphics.link.LinkForm;
import remixlab.remixvym.core.graphics.node.NodeShape;

/**
 * StyleGraph class defines all the style variables like background, node selection, 
 * node pressed, node highlights,node type and line type. Also, this class defines 
 * constants like {@link #defHeigthRoot}, {@link #defaultWidthMulti}, {@link #defFontChildSelected},
 * {@link #defFontNormal}, {@link #defFontRootSelected}, {@link #defFontRoot}, {@link #defFontSelected},
 * {@link #defHeigthChild} and {@link #defHeigthNormal}.
 * <p>
 * <b>See Examples:</b> Colors, LineStyle and NodeStyle<br><br>
 */
public class StyleGraph{
	
	/**The R component of RGB Background color. See #setBackgroundColor(int, int, int).*/	
	public int rBackgraund;
	
	/**The G component of RGB Background color. See #setBackgroundColor(int, int, int). */	
	public int gBackgraund;
	
	/** The B component of RGB Background color. See #setBackgroundColor(int, int, int).*/	
	public int bBackgraund;
	
	/** The R component of RGB None Selected Node color. See {@link #setNonSelectedColor(int, int, int)}.*/	
	public int rNonSelected;
	
	/** The G component of RGB None Selected Node color. See {@link #setNonSelectedColor(int, int, int)}.*/	
	public int gNonSelected;
	
	/** The B component of RGB None Selected Node color. See {@link #setNonSelectedColor(int, int, int)}.*/	
	public int bNonSelected;
	
	/** The R component of RGB Selected Node color. See {@link #setSelectedColor(int, int, int).*/	
	public int rSelected;
	
	/** The G component of RGB Selected Node color. See {@link #setSelectedColor(int, int, int).*/
	public int gSelected;
	
	/** The B component of RGB Selected Node color. See {@link #setSelectedColor(int, int, int).*/
	public int bSelected;
	
	/** The R component of RGB Pressed Node color. See {@link #setPressedColor(int, int, int)}.*/
	public int rPressed;
	
	/** The G component of RGB Selected Node color. See {@link #setSelectedColor(int, int, int).*/
	public int gPressed;
	
	/** The B component of RGB Selected Node color. See {@link #setSelectedColor(int, int, int).*/
	public int bPressed;
	
	/** The R component of RGB Highlight Node color. See {@link #setHighlightColor(int, int, int).*/
	public int rHighlight;
	
	/** The G component of RGB Highlight Node color. See {@link #setHighlightColor(int, int, int).*/
	public int gHighlight;
	
	/** The B component of RGB Highlight Node color. See {@link #setHighlightColor(int, int, int).*/
	public int bHighlight;
	
	public int rWithImage;
	public int gWithImage;
	public int bWithImage;
	
	/**Node type defined from a XML file. See {@link #initFromXML(XMLElement)}.*/
	public int typeNode;
	
	/**Line type defined from a XML file. See {@link #initFromXML(XMLElement)}.*/
	public int typeLine;
	
	/**Defines the default node font size.*/
	public float defFontNormal = 13;
	
	/**Defines the default node selected font size.*/
	public float defFontSelected = 16;
	
	/**Defines the default root node font size.*/
	public float defFontRoot = 21;
	
	/**Defines the default root node selected font size.*/
	public float defFontRootSelected = 24;
	
	/**Defines the default child node font size.*/
	public float defFontChild = 15;
	
	/**Defines the default child node selected font size.*/
	public float defFontChildSelected= 18;
	
	/**Defines the default minimum root node selected font size.*/
	public float minSelectedRoot = 13;
	
	/**Defines the default minimum child node selected font size.*/
	public float minSelectedChild = 12;
	
	/**Defines the default minimum node selected font size.*/
	public float minSelected = 11;
	
	//Set of fonts.
	public PFont fontNormal;
	public PFont fontSelected;
	public PFont fontRoot;
	public PFont fontRootSelected;
	public PFont fontChild;
	public PFont fontChildSelected;
	
	public PFont fontOther;
	
	//Set of sizes
	public float sizeFontNormal;
	public float sizeFontSelected;
	public float sizeFontRoot;
	public float sizeFontRootSelected;
	public float sizeFontChild;
	public float sizeFontChildSelected;
	
	
	public int defaultWidthMulti = 258;//257
	
	//Height variables for the 3 kibds of node
	
	/**Defines the default height for the root node font size.*/
	public float defHeigthRoot = 34;
	
	/**Defines the default height for the child node font size.*/
	public float defHeigthChild = 28;
	
	/**Defines the default height for the normal node font size.*/
	public float defHeigthNormal = 26;
	
	public float heigthRoot;
	public float heigthChild;
	public float heigthNormal;
	
	/**
	 * Sets the {@code RGB} Background parameters {@link #rBackgraund}, {@link #gBackgraund}, 
	 * {@link #bBackgraund}.
	 * @param r Red Color
	 * @param g Green Color
	 * @param b Blue Color
	 */
	public void setBackgroundColor(int r, int g, int b){
		rBackgraund=r;
		gBackgraund=g;
		bBackgraund=b;
	}
	
	/**
	 * Sets the {@code RGB} Node Color parameters {@link #rSelected}, {@link #gSelected}, 
	 * {@link #bSelected}.
	 * @param r Red Color
	 * @param g Green Color
	 * @param b Blue Color
	 */
	public void setSelectedColor(int r, int g, int b){
		rSelected=r;
		gSelected=g;
		bSelected=b;
	}
	
	/**
	 * Sets the {@code RGB} None Node Selected parameters {@link #rNonSelected}, {@link #gNonSelected}, 
	 * {@link #bNonSelected}.
	 * @param r Red Color
	 * @param g Green Color
	 * @param b Blue Color
	 */
	public void setNonSelectedColor(int r, int g, int b){
		rNonSelected=r;
		gNonSelected=g;
		bNonSelected=b;
	}
	
	/**
	 * Sets the {@code RGB} Node Pressed parameters {@link #rPressed}, {@link #gPressed}, 
	 * {@link #bPressed}.
	 * @param r Red Color
	 * @param g Green Color
	 * @param b Blue Color
	 */
	public void setPressedColor(int r, int g, int b){
		rPressed=r;
		gPressed=g;
		bPressed=b;
	}
	
	/**
	 * Sets the {@code RGB} Highlight Node parameters {@link #rHighlight}, {@link #gHighlight}, 
	 * {@link #bHighlight}.
	 * @param r Red Color
	 * @param g Green Color
	 * @param b Blue Color
	 */
	public void setHighlightColor(int r, int g, int b){
		rHighlight=r;
		gHighlight=g;
		bHighlight=b;
	}
	
	/**
	 * Sets the Nodes font Style. 
	 */
	public void initFonts(PApplet parent)
	{
		
		recreateFonts=true;
		fontName = "Verdana";
		
		this.sizeFontNormal = defFontNormal;
		this.sizeFontSelected = defFontSelected;
		this.sizeFontRoot = defFontRoot; 
		this.sizeFontRootSelected = defFontRootSelected;
		this.sizeFontChild = defFontChild;
		this.sizeFontChildSelected = defFontChildSelected;
		
		this.heigthRoot = defHeigthRoot;
		this.heigthChild = defHeigthChild;
		this.heigthNormal = defHeigthNormal;
		
		this.fontNormal = parent.createFont(fontName, sizeFontNormal);
		this.fontSelected = parent.createFont(fontName, sizeFontSelected);
		this.fontRoot = parent.createFont(fontName, sizeFontRoot);
		this.fontRootSelected = parent.createFont(fontName, sizeFontRootSelected);
		this.fontChild = parent.createFont(fontName, sizeFontChild);
		this.fontChildSelected = parent.createFont(fontName, sizeFontChildSelected);
		
		fontOther = parent.createFont(fontName, 13);
	}
	
	/**
	 * Sets the different size of Fonts, and Node size using a rate calculated by the 
	 * different changes into the map.
	 */
	public void changeScale(PApplet parent,double rate)
	{
		this.sizeFontNormal = (int)((double)defFontNormal*rate);
		this.sizeFontSelected = (float)((double)defFontSelected*rate);
		this.sizeFontRoot = (float)((double)defFontRoot*rate);
		this.sizeFontRootSelected = (float)((double)defFontRootSelected*rate);
		this.sizeFontChild = (float)((double)defFontChild*rate);
		this.sizeFontChildSelected = (float)((double)defFontChildSelected*rate);
		
		if(this.sizeFontSelected<minSelected) this.sizeFontSelected =minSelected;
		if(this.sizeFontChildSelected<minSelectedChild) this.sizeFontChildSelected =minSelectedChild;
		if(this.sizeFontRootSelected<minSelectedRoot) this.sizeFontRootSelected =minSelectedRoot;
		
		this.fontNormal = parent.createFont(fontName, sizeFontNormal);
		this.fontSelected = parent.createFont(fontName, sizeFontSelected);
		this.fontRoot = parent.createFont(fontName, sizeFontRoot);
		this.fontRootSelected = parent.createFont(fontName, sizeFontRootSelected);
		this.fontChild = parent.createFont(fontName, sizeFontChild);
		this.fontChildSelected = parent.createFont(fontName, sizeFontChildSelected);

		
		this.heigthRoot = (float)((double)defHeigthRoot*rate);
		this.heigthChild = (float)((double)defHeigthChild*rate);
		this.heigthNormal = (float)((double)defHeigthNormal*rate);
	}
	
	/**
	 * Sets the initial style values, implementing information from a XML file.
	 */		
	public void initFromXML(XMLElement nodeXml){
		
		typeNode=Integer.parseInt(nodeXml.getChild(0).getContent());
		typeLine= Integer.parseInt(nodeXml.getChild(1).getContent());
		
		rBackgraund=Integer.parseInt(nodeXml.getChild(2).getContent());
		gBackgraund=Integer.parseInt(nodeXml.getChild(3).getContent());
		bBackgraund=Integer.parseInt(nodeXml.getChild(4).getContent());
		
		rNonSelected=Integer.parseInt(nodeXml.getChild(5).getContent());
		gNonSelected=Integer.parseInt(nodeXml.getChild(6).getContent());
		bNonSelected=Integer.parseInt(nodeXml.getChild(7).getContent());

		rSelected=Integer.parseInt(nodeXml.getChild(8).getContent());
		gSelected=Integer.parseInt(nodeXml.getChild(9).getContent());
		bSelected=Integer.parseInt(nodeXml.getChild(10).getContent());
		
		rPressed=Integer.parseInt(nodeXml.getChild(11).getContent());
		gPressed=Integer.parseInt(nodeXml.getChild(12).getContent());
		bPressed=Integer.parseInt(nodeXml.getChild(13).getContent());
		
		rHighlight=Integer.parseInt(nodeXml.getChild(14).getContent());
		gHighlight=Integer.parseInt(nodeXml.getChild(15).getContent());
		bHighlight=Integer.parseInt(nodeXml.getChild(16).getContent());
		
		rWithImage=Integer.parseInt(nodeXml.getChild(17).getContent());
		gWithImage=Integer.parseInt(nodeXml.getChild(18).getContent());
		bWithImage=Integer.parseInt(nodeXml.getChild(19).getContent());		
	}
	
	/**
	 * Sets the different size of Fonts, and Node size using a rate calculated by the 
	 * different changes into the map.
	 */
	public void setVymWindows(PApplet parent)
	{
		fontName = "Verdana";
		defHeigthRoot = 34;
		defHeigthChild = 21;
		defHeigthNormal = 17;
		
		defFontNormal = 12;
		defFontSelected = 14;
		defFontRoot = 19;
		defFontRootSelected = 22;
		defFontChild = 14;
		defFontChildSelected= 17;
		
		defaultWidthMulti = 238;
		
		this.sizeFontNormal = defFontNormal;
		this.sizeFontSelected = defFontSelected;
		this.sizeFontRoot = defFontRoot; 
		this.sizeFontRootSelected = defFontRootSelected;
		this.sizeFontChild = defFontChild;
		this.sizeFontChildSelected = defFontChildSelected;
		
		
		this.fontNormal = parent.createFont(fontName, sizeFontNormal);
		this.fontSelected = parent.createFont(fontName, sizeFontSelected);
		this.fontRoot = parent.createFont(fontName, sizeFontRoot);
		this.fontRootSelected = parent.createFont(fontName, sizeFontRootSelected);
		this.fontChild = parent.createFont(fontName, sizeFontChild);
		this.fontChildSelected = parent.createFont(fontName, sizeFontChildSelected);
	}
	
	/**
	 * Initiate the default map values defined by {@link #initFromXML(XMLElement)} and
	 *  {@link #initFonts(PApplet)}
	 */	
	public void initDeafult(PApplet parent){
		XMLElement nodeXml;
		nodeXml = new XMLElement(parent,"resources/lineNodes.xml");
		initFromXML(nodeXml);
		initFonts(parent);
	}

	/**
	 * Returns the Node size from the {@link #styleNodes} Array List.
	 */
	public int sizeNodeStyles(){
		return styleNodes.size();
	}
	
	/**
	 * Adds the defined Node style to {@link #styleNodes} Array List.
	 */
	public void addNodeStyle(NodeShape style){
		styleNodes.add(style);
	}
	
	/**
	 * Gets the Node type from {@link #styleNodes} Array List
	 */
	public NodeShape getNodeStyle(){
		return styleNodes.get(typeNode);
	}

	public NodeShape getNodeStyle(int i){
		return styleNodes.get(i);
	}

	public int findStyle(String s){
		for(int i=0; i<sizeNodeStyles(); i++){
			//System.out.println(styleNodes.get(i).getClass().getName());
			String name = styleNodes.get(i).getClass().getName();
			name = name.substring(name.lastIndexOf(".")+1);
			//System.out.println(name+ " vs " + s);
			if(name.equalsIgnoreCase(s)){
				//typeNode=i;
				return i;
			}
		}
		return typeNode;
	}
	
	/**
	 * Returns the Node size from the {@link #styleNodes} Array List.
	 */
	public int sizeLinkStyles(){
		return styleLinks.size();
	}
	
	/**
	 * Adds the defined Link style to {@link #styleLinks} Array List.
	 */
	public void addLinkStyle(LinkForm style){
		styleLinks.add(style);
	}
	
	/**
	 * Returns the Link style from the {@link #styleNodes} Array List.
	 */
	public LinkForm getLinkStyle(){
		return styleLinks.get(typeLine);
	}
	
	ArrayList<NodeShape> styleNodes = new ArrayList<NodeShape>();
	ArrayList<LinkForm> styleLinks = new ArrayList<LinkForm>();
	
	public boolean recreateFonts;
	public String fontName;

}
